const toString = Object.prototype.toString

export const is = (val: unknown, type: string) => toString.call(val) === `[object ${type}]`

export const isUndef = (val: unknown): val is undefined => typeof val === 'undefined'

export const isObject = (val: unknown): val is Record<any, any> => val !== null && is(val, 'Object')

export const isArray = (val: unknown): val is any[] => is(val, 'Array')

export const isString = (val: unknown): val is string => is(val, 'String')

export const isDate = (val: unknown): val is Date => is(val, 'Date')

export const isNull = (val: unknown): val is null => val === null

export const isNullOrUnDef = (val: unknown): val is null | undefined => isNull(val) || isUndef(val)

export const isNumber = (val: unknown): val is null => is(val, 'Number')

export const isFunction = (val: unknown): val is null => is(val, 'Function')

export const isEmpty = <T = unknown>(val: T): val is T => {
  if (isArray(val) || isString(val)) {
    return val.length === 0
  }

  if (isObject(val)) {
    return Object.keys(val).length === 0
  }

  return false
}
